freeslot("MT_MARINE", "MT_COMMANDO", "MT_GUNNY", "MT_ELITE")
freeslot("SPR_CMDO")
//freeslot("S_CMDO_STND", "S_CMDO_WALK", "S_CMDO_JUMP", "S_CMDO_FALL", "S_CMDO_DEAD")
freeslot("S_CMDO_STND", "S_CMDO_WALK", "S_CMDO_HURT" , "S_CMDO_DEAD")
freeslot( "S_MARINE_CHRG", "S_MARINE_SHOT")
freeslot( "S_COMMANDO_CHRG", "S_COMMANDO_SHOT")
freeslot( "S_GUNNY_CHRG", "S_GUNNY_SHOT")
freeslot( "S_ELITE_CHRG", "S_ELITE_SHOT")
mobjinfo[MT_MARINE] = {
	//$Name "Marine (Pistol)"
	//$Sprite CMDOA2A8
	//$Category "Rampage Enemies"
	doomednum = 2250,
	spawnstate = S_CMDO_STND,
	spawnhealth = 75,
	seestate = S_CMDO_WALK,
	seesound = sfx_null,
	reactiontime = 1,
	attacksound = sfx_null,
	painstate = S_CMDO_HURT,
	painchance = 8192,
	painsound = sfx_null,
	meleestate = S_NULL,
	missilestate = S_MARINE_CHRG,
	deathstate = S_CMDO_DEAD,
	xdeathstate = S_NULL,
	deathsound = sfx_null,
	speed = 20,
	radius = 16*FRACUNIT,
	height = 48*FRACUNIT,
	dispoffset = 0,
	mass = 100,
	damage = 0,
	activesound = sfx_None,
	flags = MF_SOLID|MF_ENEMY|MF_SHOOTABLE,
	raisestate = S_NULL
}

mobjinfo[MT_COMMANDO] = {
	//$Name "Commando (Shotgun)"
	//$Sprite CMDOA2A8
	//$Category "Rampage Enemies"
	doomednum = 2251,
	spawnstate = S_CMDO_STND,
	spawnhealth = 75,
	seestate = S_CMDO_WALK,
	seesound = sfx_null,
	reactiontime = 1,
	attacksound = sfx_null,
	painstate = S_CMDO_HURT,
	painchance = 8192,
	painsound = sfx_null,
	meleestate = S_NULL,
	missilestate = S_COMMANDO_CHRG,
	deathstate = S_CMDO_DEAD,
	xdeathstate = S_NULL,
	deathsound = sfx_null,
	speed = 20,
	radius = 16*FRACUNIT,
	height = 48*FRACUNIT,
	dispoffset = 0,
	mass = 100,
	damage = 0,
	activesound = sfx_None,
	flags = MF_SOLID|MF_ENEMY|MF_SHOOTABLE,
	raisestate = S_NULL
}

mobjinfo[MT_GUNNY] = {
	//$Name "Gunny (Chaingunner)"
	//$Sprite CMDOA2A8
	//$Category "Rampage Enemies"
	doomednum = 2252,
	spawnstate = S_CMDO_STND,
	spawnhealth = 100,
	seestate = S_CMDO_WALK,
	seesound = sfx_null,
	reactiontime = 1,
	attacksound = sfx_null,
	painstate = S_CMDO_HURT,
	painchance = 8192,
	painsound = sfx_null,
	meleestate = S_NULL,
	missilestate = S_GUNNY_CHRG,
	deathstate = S_CMDO_DEAD,
	xdeathstate = S_NULL,
	deathsound = sfx_null,
	speed = 20,
	radius = 16*FRACUNIT,
	height = 48*FRACUNIT,
	dispoffset = 0,
	mass = 100,
	damage = 0,
	activesound = sfx_None,
	flags = MF_SOLID|MF_ENEMY|MF_SHOOTABLE,
	raisestate = S_NULL
}

mobjinfo[MT_ELITE] = {
	//$Name "Elite (Rockets)"
	//$Sprite CMDOA2A8
	//$Category "Rampage Enemies"
	doomednum = 2253,
	spawnstate = S_CMDO_STND,
	spawnhealth = 100,
	seestate = S_CMDO_WALK,
	seesound = sfx_null,
	reactiontime = 1,
	attacksound = sfx_null,
	painstate = S_CMDO_HURT,
	painchance = 8192,
	painsound = sfx_null,
	meleestate = S_NULL,
	missilestate = S_ELITE_CHRG,
	deathstate = S_CMDO_DEAD,
	xdeathstate = S_NULL,
	deathsound = sfx_null,
	speed = 20,
	radius = 16*FRACUNIT,
	height = 48*FRACUNIT,
	dispoffset = 0,
	mass = 100,
	damage = 0,
	activesound = sfx_None,
	flags = MF_SOLID|MF_ENEMY|MF_SHOOTABLE,
	raisestate = S_NULL
}

local function EnemyHitscan(mo, damage, hspread, vspread, range, step, angal, aimung, lag)
	if not (mo.target and mo.target.valid) then return end
	local angle = angal
	local dx
	local dy
	local dz
	local dxy
	local aim = aimung
	if angle == nil then
		angle = R_PointToAngle2(mo.x, mo.y, mo.target.x-mo.target.momx*lag, mo.target.y-mo.target.momy*lag)
	end
	if aim == nil then
		dx = mo.x - (mo.target.x-mo.target.momx*lag)
		dy = mo.y - (mo.target.y-mo.target.momy*lag)
		dz = mo.z+mo.height/2 - (mo.target.z+mo.target.height/2-mo.target.momz*lag)
		dxy = P_AproxDistance(dx, dy)
		aim = -R_PointToAngle2(0, 0, dxy, dz)
	end
	local sp1 = FixedAngle(P_RandomRange(-hspread, hspread))
	local sp2 = FixedAngle(P_RandomRange(-vspread, vspread))
	local targetlist = P_AngleRaycast{x = mo.x, y = mo.y, z = mo.z+24*FU, ang = angle + sp1, zang = aim + sp2, distance = range or 4096*FU, steps = step or 256, tclip = true, lclip = true, ignore = mo, callback2 = P_SpawnMobj, larg = MT_SMOKE}
	if not next(targetlist) then return false end
	local target = targetlist[1][4]
	if target.type == MT_PLAYER then
		if CanPlayerHurtPlayer(target.player, target.player, 0, 0) == true then
			Playerdamage(target, mo, mo, damage or 5, 0, true)
			return true
		end
	else
		P_DamageMobj(target, mo, mo, damage or 5, 0)
		return true
	end
end

local function EnemyShotgun(mo, damage, hspread, vspread, range, step, amount, angal, aimung, lag)
	if not (mo.target and mo.target.valid) then return end
	local angle = angal
	local dx
	local dy
	local dz
	local dxy
	local aim = aimung
	if angle == nil then
		angle = R_PointToAngle2(mo.x, mo.y, mo.target.x-mo.target.momx*2, mo.target.y-mo.target.momy*2)
	end
	if aim == nil then
		dx = mo.x - (mo.target.x-mo.target.momx*2)
		dy = mo.y - (mo.target.y-mo.target.momy*2)
		dz = mo.z+mo.height/2 - (mo.target.z+mo.target.height/2-mo.target.momz*2)
		dxy = P_AproxDistance(dx, dy)
		aim = -R_PointToAngle2(0, 0, dxy, dz)
	end
	for i = 1,amount do
		local d = P_RandomRange(damage[1], damage[2])
		EnemyHitscan(mo, d, hspread, vspread, range, step, angle, aim)
	end
end

states[S_CMDO_STND] = {
	sprite = SPR_CMDO,
	frame = A,
	tics = 1,
	action = A_Look,
	nextstate = S_CMDO_STND
}

function A_NullChase(actor, var1, var2)
	A_Chase(actor, 0, 0)
end

states[S_CMDO_WALK] = {
	sprite = SPR_CMDO,
	frame = B|FF_ANIMATE|FF_GLOBALANIM,
	var1 = 7,
	var2 = 4,
	tics = 3,
	action = A_NullChase,
	nextstate = S_CMDO_WALK
}

function A_MarinePistol(actor, var1, var2)
	local d = P_RandomRange(5,15)
	A_FaceTarget(actor, var1, var2)
	S_StartSound(mo, sfx_pistol)
	EnemyHitscan(actor, d, 5*FU, 5*FU/4, 2048*FU, nil, nil, nil, 0)
	if ultimatemode then
		actor.reactiontime = actor.info.reactiontime*TICRATE
	else
		actor.reactiontime = actor.info.reactiontime*TICRATE*2
	end
end

states[S_MARINE_CHRG] = {
	sprite = SPR_CMDO,
	frame = L,
	tics = 10,
	action = A_FaceTarget,
	nextstate = S_MARINE_SHOT
}

states[S_MARINE_SHOT] = {
	sprite = SPR_CMDO,
	frame = J,
	tics = 8,
	action = A_MarinePistol,
	nextstate = S_CMDO_WALK
}

function A_CommandoShot(actor, var1, var2)
	A_FaceTarget(actor, var1, var2)
	S_StartSound(mo, sfx_shotfr)
	EnemyShotgun(mo, {5,15}, 4*FU, FU, 2048*FU, nil, 3, nil, nil, 0)
	//EnemyHitscan(actor, d, 5*FU, 5*FU/4, 2048*FU, nil, nil, nil, 0)
	if ultimatemode then
		actor.reactiontime = actor.info.reactiontime*TICRATE
	else
		actor.reactiontime = actor.info.reactiontime*TICRATE*2
	end
end

states[S_COMMANDO_CHRG] = {
	sprite = SPR_CMDO,
	frame = L,
	tics = 10,
	action = A_FaceTarget,
	nextstate = S_COMMANDO_SHOT
}

states[S_COMMANDO_SHOT] = {
	sprite = SPR_CMDO,
	frame = J,
	tics = 8,
	action = A_CommandoShot,
	nextstate = S_CMDO_WALK
}

function A_GunnyShot(actor, var1, var2)	
	if not (actor.target and actor.target.valid) then
		//print(3)
		actor.state = actor.info.seestate
		if ultimatemode then
			actor.reactiontime = actor.info.reactiontime*TICRATE
		else
			actor.reactiontime = actor.info.reactiontime*TICRATE*2
		end
		return
	end
	if (P_CheckSight(actor, actor.target) and R_PointToDist2(actor.x, actor.y, actor.target.x, actor.target.y) <= 4096*FU) or P_RandomRange (1, 20) <= 3 then //15% chance to keep firing per check
		//print(2)
		local d = P_RandomRange(5,15)
		A_FaceTarget(actor, var1, var2)
		S_StartSound(mo, sfx_chaing)
		EnemyHitscan(actor, d, 5*FU, 5*FU/4, 2048*FU, nil, nil, nil, 0)
		//EnemyShotgun(mo, {5,15}, 4*FU, FU, 2048*FU, nil, 3, nil, nil, 0)
	else
		//print(3)
		actor.state = actor.info.seestate
		if ultimatemode then
			actor.reactiontime = actor.info.reactiontime*TICRATE
		else
			actor.reactiontime = actor.info.reactiontime*TICRATE*2
		end
	end
end

states[S_GUNNY_CHRG] = {
	sprite = SPR_CMDO,
	frame = L,
	tics = 10,
	action = A_FaceTarget,
	nextstate = S_GUNNY_SHOT
}

states[S_GUNNY_SHOT] = {
	sprite = SPR_CMDO,
	frame = J,
	tics = 4,
	action = A_GunnyShot,
	nextstate = S_GUNNY_SHOT
}

function A_EliteShot(actor, var1, var2)	
	A_FaceTarget(actor, var1, var2)
	S_StartSound(mo, sfx_cannon)
	P_SpawnMissile(mo, mo.target, MT_RMPROCKET)
	if ultimatemode then
		actor.reactiontime = actor.info.reactiontime*TICRATE
	else
		actor.reactiontime = actor.info.reactiontime*TICRATE*2
	end
end

states[S_ELITE_CHRG] = {
	sprite = SPR_CMDO,
	frame = L,
	tics = 10,
	action = A_FaceTarget,
	nextstate = S_GUNNY_SHOT
}

states[S_ELITE_SHOT] = {
	sprite = SPR_CMDO,
	frame = J,
	tics = 4,
	action = A_EliteShot,
	nextstate = S_GUNNY_SHOT
}

states[S_CMDO_DEAD] = {
	sprite = SPR_CMDO,
	frame = M,
	tics = -1,
	nextstate = S_CMDO_DEAD
}

states[S_CMDO_HURT] = {
	sprite = SPR_CMDO,
	frame = N,
	tics = 3,
	nextstate = S_CMDO_WALK
}

mobjinfo[MT_MARINE].bloodcolor = SKINCOLOR_RED
mobjinfo[MT_MARINE].rfwpainchance = 100
mobjinfo[MT_COMMANDO].bloodcolor = SKINCOLOR_RED
mobjinfo[MT_COMMANDO].rfwpainchance = 85
mobjinfo[MT_GUNNY].bloodcolor = SKINCOLOR_RED
mobjinfo[MT_GUNNY].rfwpainchance = 85
mobjinfo[MT_ELITE].bloodcolor = SKINCOLOR_RED
mobjinfo[MT_ELITE].rfwpainchance = 75

mobjinfo[MT_MARINE].dropitem = MT_BULLETS
mobjinfo[MT_COMMANDO].dropitem = MT_SHOTGUN
mobjinfo[MT_GUNNY].dropitem = MT_CHAINGUN
mobjinfo[MT_ELITE].dropitem = MT_ROCKETLAUNCHER

//mo.translation = "RedToBlue"

addHook("MobjSpawn", function(mo)
	mo.translation = "Marine"
end, MT_MARINE)

addHook("MobjSpawn", function(mo)
	mo.translation = "Commando"
end, MT_COMMANDO)

addHook("MobjSpawn", function(mo)
	mo.translation = "Gunny"
end, MT_GUNNY)

addHook("MobjSpawn", function(mo)
	mo.translation = "Elite"
end, MT_ELITE)

/*addHook("MobjThinker", function(mo)
	if not mo.health then return end //dead lmfao
	if not mo.target then //find targets
		mo.cmdweaponcooldown = 20
		local target = P_LookForPlayers(mo, 2048*FU, false, false)
		if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
			P_SetMobjStateNF(mo, S_CMDO_STND)
		elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
			P_SetMobjStateNF(mo, S_CMDO_WALK)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
			P_SetMobjStateNF(mo, S_CMDO_JUMP)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
			P_SetMobjStateNF(mo, S_CMDO_FALL)
		end
		if not mo.target then return end //we still don't have a target
	end
	local dist = R_PointToDist2(mo.x, mo.y, mo.target.x, mo.target.y)
	if mo.strafedir == nil then
		mo.strafedir = 0 //angle 0 is forward, 90 is left, 180 is back, 270 is right
	end
	if mo.forcedir == nil then
		mo.forcedir = 0 //don't change strafe directions if this is above 0
	end
	if mo.switchtimer == nil then
		mo.switchtimer = P_RandomRange(7, 35)
	end
	if dist <= 512*mo.target.scale and dist >= 384*mo.target.scale and mo.forcedir == 0 then
		if (mo.strafedir ~= ANGLE_90 and mo.strafedir ~= ANGLE_270) or not mo.switchtimer then
			if P_RandomKey(2) then
				mo.strafedir = ANGLE_90 //left
				mo.switchtimer = P_RandomRange(7, 35)
			else
				mo.strafedir = ANGLE_270 //right
				mo.switchtimer = P_RandomRange(7, 35)
			end
		end
		mo.switchtimer = max($-1, 0)
		if P_IsObjectOnGround(mo) and (not P_RandomRange(0, 49)) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	elseif dist >= 512*mo.target.scale and mo.forcedir == 0 then
		mo.strafedir = 0
	elseif mo.forcedir == 0 then
		mo.strafedir = ANGLE_180
		if P_IsObjectOnGround(mo) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	end
	if not P_CheckPosition(mo, mo.x+mo.momx, mo.y+mo.momy) then
		mo.strafedir = FixedAngle(P_RandomRange(0, 360*FU-1))
		mo.forcedir = 10
	end
	if mo.forcedir > 0 then
		mo.forcedir = max($-1, 0)
	end
	mo.angle = R_PointToAngle2(mo.x, mo.y, mo.target.x-mo.target.momx, mo.target.y-mo.target.momy)
	if P_IsObjectOnGround(mo) then
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*3/2)
	else
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*1/3)
	end
	if abs(mo.momx)+abs(mo.momy) > 14*mo.scale then
		P_InstaThrust(mo, R_PointToAngle2(0, 0, mo.momx, mo.momy), 14*mo.scale)
	end
	if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
		P_SetMobjStateNF(mo, S_CMDO_STND)
	elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
		P_SetMobjStateNF(mo, S_CMDO_WALK)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
		P_SetMobjStateNF(mo, S_CMDO_JUMP)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
		P_SetMobjStateNF(mo, S_CMDO_FALL)
	end
	//weapon time firerate 36 tics
	if mo.cmdweaponcooldown == nil then
		mo.cmdweaponcooldown = 20
	end
	if dist <= 1024*FU and mo.cmdweaponcooldown == 0 then
		mo.cmdweaponcooldown = 36
		EnemyHitscan(mo, 5, 5*FU, 5*FU/2, 2048*FU, nil, nil, nil, 1)
		S_StartSound(mo, sfx_pistol)
	end
	if mo.cmdweaponcooldown > 0 then
		mo.cmdweaponcooldown = max($-1, 0)
	end
end, MT_MARINE)

addHook("MobjThinker", function(mo)
	if not mo.health then return end //dead lmfao
	if not mo.target then //find targets
		mo.cmdweaponcooldown = 20
		local target = P_LookForPlayers(mo, 2048*FU, false, false)
		if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
			P_SetMobjStateNF(mo, S_CMDO_STND)
		elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
			P_SetMobjStateNF(mo, S_CMDO_WALK)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
			P_SetMobjStateNF(mo, S_CMDO_JUMP)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
			P_SetMobjStateNF(mo, S_CMDO_FALL)
		end
		if not mo.target then return end //we still don't have a target
	end
	local dist = R_PointToDist2(mo.x, mo.y, mo.target.x, mo.target.y)
	if mo.strafedir == nil then
		mo.strafedir = 0 //angle 0 is forward, 90 is left, 180 is back, 270 is right
	end
	if mo.forcedir == nil then
		mo.forcedir = 0 //don't change strafe directions if this is above 0
	end
	if mo.switchtimer == nil then
		mo.switchtimer = P_RandomRange(7, 35)
	end
	if dist <= 512*mo.target.scale and dist >= 384*mo.target.scale and mo.forcedir == 0 then
		if (mo.strafedir ~= ANGLE_90 and mo.strafedir ~= ANGLE_270) or not mo.switchtimer then
			if P_RandomKey(2) then
				mo.strafedir = ANGLE_90 //left
				mo.switchtimer = P_RandomRange(7, 35)
			else
				mo.strafedir = ANGLE_270 //right
				mo.switchtimer = P_RandomRange(7, 35)
			end
		end
		mo.switchtimer = max($-1, 0)
		if P_IsObjectOnGround(mo) and (not P_RandomRange(0, 49)) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	elseif dist >= 512*mo.target.scale and mo.forcedir == 0 then
		mo.strafedir = 0
	elseif mo.forcedir == 0 then
		mo.strafedir = ANGLE_180
		if P_IsObjectOnGround(mo) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	end
	if not P_CheckPosition(mo, mo.x+mo.momx, mo.y+mo.momy) then
		mo.strafedir = FixedAngle(P_RandomRange(0, 360*FU-1))
		mo.forcedir = 10
	end
	if mo.forcedir > 0 then
		mo.forcedir = max($-1, 0)
	end
	mo.angle = R_PointToAngle2(mo.x, mo.y, mo.target.x-mo.target.momx, mo.target.y-mo.target.momy)
	if P_IsObjectOnGround(mo) then
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*3/2)
	else
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*1/3)
	end
	if abs(mo.momx)+abs(mo.momy) > 14*mo.scale then
		P_InstaThrust(mo, R_PointToAngle2(0, 0, mo.momx, mo.momy), 14*mo.scale)
	end
	if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
		P_SetMobjStateNF(mo, S_CMDO_STND)
	elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
		P_SetMobjStateNF(mo, S_CMDO_WALK)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
		P_SetMobjStateNF(mo, S_CMDO_JUMP)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
		P_SetMobjStateNF(mo, S_CMDO_FALL)
	end
	//weapon time firerate 36 tics
	if mo.cmdweaponcooldown == nil then
		mo.cmdweaponcooldown = 20
	end
	if dist <= 784*FU and mo.cmdweaponcooldown == 0 then
		mo.cmdweaponcooldown = 36
		EnemyShotgun(mo, {5,5}, 4*FU, 2*FU, 2048*FU, nil, 3, nil, nil, 2)
		S_StartSound(mo, sfx_shotfr)
	end
	if mo.cmdweaponcooldown > 0 then
		mo.cmdweaponcooldown = max($-1, 0)
	end
end, MT_COMMANDO)

addHook("MobjThinker", function(mo)
	if not mo.health then return end //dead lmfao
	if not mo.target then //find targets
		mo.cmdweaponcooldown = 20
		local target = P_LookForPlayers(mo, 2048*FU, false, false)
		if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
			P_SetMobjStateNF(mo, S_CMDO_STND)
		elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
			P_SetMobjStateNF(mo, S_CMDO_WALK)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
			P_SetMobjStateNF(mo, S_CMDO_JUMP)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
			P_SetMobjStateNF(mo, S_CMDO_FALL)
		end

		if not mo.target then return end //we still don't have a target
	end
	local dist = R_PointToDist2(mo.x, mo.y, mo.target.x, mo.target.y)
	if mo.strafedir == nil then
		mo.strafedir = 0 //angle 0 is forward, 90 is left, 180 is back, 270 is right
	end
	if mo.forcedir == nil then
		mo.forcedir = 0 //don't change strafe directions if this is above 0
	end
	if mo.switchtimer == nil then
		mo.switchtimer = P_RandomRange(7, 35)
	end
	if dist <= 512*mo.target.scale and dist >= 384*mo.target.scale and mo.forcedir == 0 then
		if (mo.strafedir ~= ANGLE_90 and mo.strafedir ~= ANGLE_270) or not mo.switchtimer then
			if P_RandomKey(2) then
				mo.strafedir = ANGLE_90 //left
				mo.switchtimer = P_RandomRange(7, 35)
			else
				mo.strafedir = ANGLE_270 //right
				mo.switchtimer = P_RandomRange(7, 35)
			end
		end
		mo.switchtimer = max($-1, 0)
		if P_IsObjectOnGround(mo) and (not P_RandomRange(0, 49)) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	elseif dist >= 512*mo.target.scale and mo.forcedir == 0 then
		mo.strafedir = 0
	elseif mo.forcedir == 0 then
		mo.strafedir = ANGLE_180
		if P_IsObjectOnGround(mo) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	end
	if not P_CheckPosition(mo, mo.x+mo.momx, mo.y+mo.momy) then
		mo.strafedir = FixedAngle(P_RandomRange(0, 360*FU-1))
		mo.forcedir = 10
	end
	if mo.forcedir > 0 then
		mo.forcedir = max($-1, 0)
	end
	mo.angle = R_PointToAngle2(mo.x, mo.y, mo.target.x-mo.target.momx, mo.target.y-mo.target.momy)
	if P_IsObjectOnGround(mo) then
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*3/2)
	else
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*1/3)
	end
	if abs(mo.momx)+abs(mo.momy) > 14*mo.scale then
		P_InstaThrust(mo, R_PointToAngle2(0, 0, mo.momx, mo.momy), 14*mo.scale)
	end
	if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
		P_SetMobjStateNF(mo, S_CMDO_STND)
	elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
		P_SetMobjStateNF(mo, S_CMDO_WALK)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
		P_SetMobjStateNF(mo, S_CMDO_JUMP)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
		P_SetMobjStateNF(mo, S_CMDO_FALL)
	end
	//weapon time firerate 36 tics
	if mo.cmdweaponcooldown == nil then
		mo.cmdweaponcooldown = 20
	end
	if dist <= 512*FU and mo.cmdweaponcooldown == 0 then
		mo.cmdweaponcooldown = 4
		EnemyHitscan(mo, 5, 5*FU, 5*FU/2, 2048*FU, nil, nil, nil, 3)
		S_StartSound(mo, sfx_chaing)
	end
	if mo.cmdweaponcooldown > 0 then
		mo.cmdweaponcooldown = max($-1, 0)
	end
end, MT_GUNNY)

addHook("MobjThinker", function(mo)
	if not mo.health then return end //dead lmfao
	if not mo.target then //find targets
		mo.cmdweaponcooldown = 20
		local target = P_LookForPlayers(mo, 2048*FU, false, false)
		if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
			P_SetMobjStateNF(mo, S_CMDO_STND)
		elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
			P_SetMobjStateNF(mo, S_CMDO_WALK)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
			P_SetMobjStateNF(mo, S_CMDO_JUMP)
		elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
			P_SetMobjStateNF(mo, S_CMDO_FALL)
		end
		if not mo.target then return end //we still don't have a target
	end
	local dist = R_PointToDist2(mo.x, mo.y, mo.target.x, mo.target.y)
	if mo.strafedir == nil then
		mo.strafedir = 0 //angle 0 is forward, 90 is left, 180 is back, 270 is right
	end
	if mo.forcedir == nil then
		mo.forcedir = 0 //don't change strafe directions if this is above 0
	end
	if mo.switchtimer == nil then
		mo.switchtimer = P_RandomRange(7, 35)
	end
	if dist <= 512*mo.target.scale and dist >= 384*mo.target.scale and mo.forcedir == 0 then
		if (mo.strafedir ~= ANGLE_90 and mo.strafedir ~= ANGLE_270) or not mo.switchtimer then
			if P_RandomKey(2) then
				mo.strafedir = ANGLE_90 //left
				mo.switchtimer = P_RandomRange(7, 35)
			else
				mo.strafedir = ANGLE_270 //right
				mo.switchtimer = P_RandomRange(7, 35)
			end
		end
		mo.switchtimer = max($-1, 0)
		if P_IsObjectOnGround(mo) and (not P_RandomRange(0, 49)) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	elseif dist >= 512*mo.target.scale and mo.forcedir == 0 then
		mo.strafedir = 0
	elseif mo.forcedir == 0 then
		mo.strafedir = ANGLE_180
		if P_IsObjectOnGround(mo) then
			P_SetObjectMomZ(mo, P_RandomRange(5*FU, 15*FU/2), true)
			S_StartSound(mo, sfx_jump)
		end
	end
	if not P_CheckPosition(mo, mo.x+mo.momx, mo.y+mo.momy) then
		mo.strafedir = FixedAngle(P_RandomRange(0, 360*FU-1))
		mo.forcedir = 10
	end
	if mo.forcedir > 0 then
		mo.forcedir = max($-1, 0)
	end
	mo.angle = R_PointToAngle2(mo.x, mo.y, mo.target.x-mo.target.momx, mo.target.y-mo.target.momy)
	if P_IsObjectOnGround(mo) then
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*3/2)
	else
		P_Thrust(mo, mo.angle+mo.strafedir, mo.scale*1/3)
	end
	if abs(mo.momx)+abs(mo.momy) > 14*mo.scale then
		P_InstaThrust(mo, R_PointToAngle2(0, 0, mo.momx, mo.momy), 14*mo.scale)
	end
	if abs(mo.momx)+abs(mo.momy) <= 5*mo.scale and P_IsObjectOnGround(mo) and mo.state ~= S_CMDO_STND then
		P_SetMobjStateNF(mo, S_CMDO_STND)
	elseif P_IsObjectOnGround(mo) and abs(mo.momx)+abs(mo.momy) > 5*mo.scale and mo.state ~= S_CMDO_WALK then
		P_SetMobjStateNF(mo, S_CMDO_WALK)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz >= 0 and P_MobjFlip(mo) == 1) or (mo.momz <= 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_JUMP then
		P_SetMobjStateNF(mo, S_CMDO_JUMP)
	elseif (not P_IsObjectOnGround(mo)) and (mo.momz < 0 and P_MobjFlip(mo) == 1) or (mo.momz > 0 and P_MobjFlip(mo) == -1) and mo.state ~= S_CMDO_FALL then
		P_SetMobjStateNF(mo, S_CMDO_FALL)
	end
	//weapon time firerate 36 tics
	if mo.cmdweaponcooldown == nil then
		mo.cmdweaponcooldown = 20
	end
	if dist <= 512*FU and mo.cmdweaponcooldown == 0 then
		mo.cmdweaponcooldown = 26
		P_SpawnMissile(mo, mo.target, MT_RMPROCKET)
		S_StartSound(mo, sfx_cannon)
	end
	if mo.cmdweaponcooldown > 0 then
		mo.cmdweaponcooldown = max($-1, 0)
	end
end, MT_ELITE)*/

freeslot("MT_MARINE_WALKA")
freeslot("S_I_WALK_A_LONELY_ROAD_THE_ONLY_ONE_THAT_I_HAVE_EVER_KNOWN")
//freeslot("SPR_BTCH")
mobjinfo[MT_MARINE_WALKA] = {
	//$Name "Marine Spawner (Cutscene)"
	//$Sprite BTCHA0
	//$Category "Biohazard Containment Folder (DO NOT OPEN!!!)"
	spawnstate = S_I_WALK_A_LONELY_ROAD_THE_ONLY_ONE_THAT_I_HAVE_EVER_KNOWN,
	spawnhealth = 9999,
	seestate = S_NULL,
	seesound = sfx_none,
	reactiontime = 1,
	attacksound = sfx_none,
	painstate = S_NULL,
	painchance = 8192,
	painsound = sfx_none,
	meleestate = S_NULL,
	missilestate = S_NULL,
	deathstate = S_NULL,
	xdeathstate = S_NULL,
	deathsound = sfx_none,
	speed = 0,
	radius = 1,
	height = 1,
	dispoffset = 0,
	mass = 100,
	damage = 0,
	activesound = sfx_None,
	flags = MF_NOCLIP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_SCENERY,
	raisestate = S_NULL
}

freeslot("sfx_march")

function A_FUCK_1(actor, var1, var2)
	P_InstaThrust(actor, actor.angle, 8*FU)
	//if not S_SoundPlaying(actor.subsector.sector, sfx_march) then
	//	S_StartSound(actor.subsector.sector, sfx_march)
	//end
	//print(1)
end

states[S_I_WALK_A_LONELY_ROAD_THE_ONLY_ONE_THAT_I_HAVE_EVER_KNOWN] = {
	sprite = SPR_CMDO,
	frame = B|FF_ANIMATE|FF_GLOBALANIM,
	var1 = 7,
	var2 = 4,
	tics = 1,
	action = A_FUCK_1,
	nextstate = S_I_WALK_A_LONELY_ROAD_THE_ONLY_ONE_THAT_I_HAVE_EVER_KNOWN
}

freeslot("MT_MARINE_SPAWNER_CUTSCENE")
freeslot("S_MARINE_SPAWNER_CUTSCENE")
//freeslot("SPR_BTCH")
mobjinfo[MT_MARINE_SPAWNER_CUTSCENE] = {
	//$Name "Marine Spawner (Cutscene)"
	//$Sprite BTCHA0
	//$Category "Biohazard Containment Folder (DO NOT OPEN!!!)"
	doomednum = 69, //SIX NINE PHONK MANGOS MODE
	spawnstate = S_MARINE_SPAWNER_CUTSCENE,
	spawnhealth = 9999,
	seestate = S_NULL,
	seesound = sfx_none,
	reactiontime = 1,
	attacksound = sfx_none,
	painstate = S_NULL,
	painchance = 8192,
	painsound = sfx_none,
	meleestate = S_NULL,
	missilestate = S_NULL,
	deathstate = S_NULL,
	xdeathstate = S_NULL,
	deathsound = sfx_none,
	speed = 0,
	radius = 1,
	height = 1,
	dispoffset = 0,
	mass = 100,
	damage = 0,
	activesound = sfx_None,
	flags = MF_NOCLIP|MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC,
	raisestate = S_NULL
}

local function L_Choose(...)
	local args = {...}
	local choice = P_RandomRange(1,#args)
	return args[choice]
end

function A_FUCK_2(actor, var1, var2)
	local marineRAGH = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_MARINE_WALKA)
	marineRAGH.angle = actor.angle
	marineRAGH.translation = L_Choose("Marine", "Commando", "Gunny", "Elite")
	marineRAGH.fuse = 260
end

states[S_MARINE_SPAWNER_CUTSCENE] = {
	sprite = SPR_NULL,
	frame = A,
	tics = 15,
	action = A_FUCK_2,
	nextstate = S_MARINE_SPAWNER_CUTSCENE
}